using System.Collections;
using System.Collections.Generic;
using Cinemachine;
using UnityEngine;

public class CameraManager : MonoBehaviour
{
    public static CameraManager Instance;

    [SerializeField] private CinemachineVirtualCamera[] allVirtualCameras;

    [SerializeField] private float fallPanAmount = .25f;
    [SerializeField] private float fallYPanTime = .35f;

    [SerializeField] private Transform followTarget;

    public float fallSpeedYDampingChangeThreshold = -15f;

    public bool IsLerpingYDamping { get; private set; }

    public bool LerpedFromPlayerFalling { get; set; }

    private Coroutine _lerpYPanCoroutine;
    private CinemachineVirtualCamera _currentVirtualCamera;
    private CinemachineFramingTransposer _framingTransposer;
    private Coroutine _cameraOffsetCoroutine;
    private float _normalYPanAmount;


    private Coroutine _cameraFocusCoroutine;
    private Coroutine _cameraRecoveryFocusCoroutine;
    private float originalOrthographicSize;
    private void Awake()
    {
        Instance = this;

        for (int i = 0; i < allVirtualCameras.Length; i++)
        {
            if (allVirtualCameras[i].enabled)
            {
                _currentVirtualCamera = allVirtualCameras[i];
                _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
            }
        }
        _normalYPanAmount = _framingTransposer.m_YDamping;
    }

    /// <summary>
    /// 玩家向上向下看
    /// </summary>
    /// <param name="lookDownScreenY"></param>
    /// <param name="duration"></param>
    public void CameraLookView(float lookDownScreenY,float duration)
    {
        if (_cameraOffsetCoroutine != null)
            StopCoroutine(_cameraOffsetCoroutine);

        _cameraOffsetCoroutine = StartCoroutine(CameraLookViewCo(lookDownScreenY, duration));
    }

    private IEnumerator CameraLookViewCo(float screenY, float duration)
    {
        CinemachineCameraOffset cinemachineCameraOffset = _currentVirtualCamera.GetComponent<CinemachineCameraOffset>();
        float startScreenY = cinemachineCameraOffset.m_Offset.y;
        float endScreenY = screenY;
        float timer = 0;
        while (timer < duration)
        {
            timer += Time.deltaTime;

            cinemachineCameraOffset.m_Offset.y = Mathf.Lerp(startScreenY, endScreenY, timer / duration);

            yield return null;
        }
    }

    /// <summary>
    /// 当下落到达一定速度时触发相机YDamping减少，让相机能够更快的跟随玩家
    /// </summary>
    /// <param name="isPlayerFalling"></param>
    public void LerpYDamping(bool isPlayerFalling)
    {
        _lerpYPanCoroutine ??= StartCoroutine(LerpYActionCo(isPlayerFalling));
    }
    public IEnumerator LerpYActionCo(bool isPlayerFalling)
    {
        float startDampAmount = _framingTransposer.m_YDamping;
        float endDampAmount;
        if (isPlayerFalling)
        {
            endDampAmount = fallPanAmount;
            LerpedFromPlayerFalling = true;
        }
        else
        {
            endDampAmount = _normalYPanAmount;
            LerpedFromPlayerFalling = false;
        }

        float elapsed = 0;
        while (elapsed < fallYPanTime)
        {
            elapsed += Time.deltaTime;

            float lerpedPanAmount = Mathf.Lerp(startDampAmount, endDampAmount, elapsed / fallPanAmount);
            _framingTransposer.m_YDamping = lerpedPanAmount;

            yield return null;
        }
        _lerpYPanCoroutine = null;
    }

    /// <summary>
    /// 竖直交换相机
    /// </summary>
    /// <param name="cameraFromleft"></param>
    /// <param name="cameraFromRight"></param>
    /// <param name="triggerExitDirection"></param>
    public void SwapCameraVertical(CinemachineVirtualCamera cameraFromDown, CinemachineVirtualCamera cameraFromUp, Vector2 triggerExitDirection)
    {
        if (_currentVirtualCamera == cameraFromDown && triggerExitDirection.y > 0f)
        {
            cameraFromUp.enabled = true;

            cameraFromDown.enabled = false;

            _currentVirtualCamera = cameraFromUp;


            _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
        }

        else if (_currentVirtualCamera == cameraFromUp && triggerExitDirection.y < 0f)
        {
            cameraFromDown.enabled = true;

            cameraFromUp.enabled = false;

            _currentVirtualCamera = cameraFromDown;

            _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
        }
    }
    /// <summary>
    /// 水平交换相机
    /// </summary>
    /// <param name="cameraFromleft"></param>
    /// <param name="cameraFromRight"></param>
    /// <param name="triggerExitDirection"></param>
    public void SwapCameraHorizontal(CinemachineVirtualCamera cameraFromleft, CinemachineVirtualCamera cameraFromRight, Vector2 triggerExitDirection)
    {
        if (_currentVirtualCamera == cameraFromleft && triggerExitDirection.x > 0f)
        {
            cameraFromRight.enabled = true;

            cameraFromleft.enabled = false;

            _currentVirtualCamera = cameraFromRight;

            _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
        }

        else if (_currentVirtualCamera == cameraFromRight && triggerExitDirection.x < 0f)
        {
            cameraFromleft.enabled = true;

            cameraFromRight.enabled = false;

            _currentVirtualCamera = cameraFromleft;

            _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
        }
    }
    
    public void SwapCamera(CinemachineVirtualCamera targetCamera)
    {
        _currentVirtualCamera.enabled = false;

        targetCamera.enabled = true;

        _currentVirtualCamera = targetCamera;

        _framingTransposer = _currentVirtualCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
    }

    /// <summary>
    /// 基于世界坐标的相机聚焦
    /// </summary>
    /// <param name="worldTargetPos">世界空间中的目标点</param>
    /// <param name="pushDepth">正交大小变化量</param>
    /// <param name="duration">过渡时间</param>
    public void CameraFocus(float pushDepth, float duration)
    {
        if (_currentVirtualCamera == null || _framingTransposer == null || followTarget == null)
            return;
        originalOrthographicSize = _currentVirtualCamera.m_Lens.OrthographicSize;

        _cameraFocusCoroutine ??= StartCoroutine(CameraFocusCo(pushDepth, duration));

    }
    private IEnumerator CameraFocusCo(float pushDepth, float duration)
    {
        float timer = 0;
        float endOrthographicSize = originalOrthographicSize + pushDepth;
        CinemachineVirtualCamera currentVirtualCamera = _currentVirtualCamera;

        Vector2 startDamping = new(_framingTransposer.m_XDamping, _framingTransposer.m_YDamping);
        _framingTransposer.m_XDamping = .5f;
        _framingTransposer.m_YDamping = .5f;

        while (timer < duration)
        {
            timer += Time.deltaTime;
            // 限制进度不超过1，避免因浮点误差导致过度
            float progress = Mathf.Min(timer / duration, 1f);
            // 修复2：使用SmoothStep增强过渡手感（可选）
            float smoothProgress = 1 - Mathf.Pow(1 - progress, 3); // 3次幂曲线，可调整幂次控制加速程度

            // 插值正交大小
            currentVirtualCamera.m_Lens.OrthographicSize = Mathf.Lerp(originalOrthographicSize, endOrthographicSize, smoothProgress);

            yield return null;
        }

        _framingTransposer.m_XDamping = startDamping.x;
        _framingTransposer.m_YDamping = startDamping.y;
        
        _cameraFocusCoroutine = null;
    }

    public void CameraRecoveryFocus(float duration)
    {
        _cameraRecoveryFocusCoroutine ??= StartCoroutine(CameraRecoveryFocusCo(duration));
    }
    private IEnumerator CameraRecoveryFocusCo(float duration)
    {
        float timer = 0;
        float currentCameraOrthographicSize = _currentVirtualCamera.m_Lens.OrthographicSize;
        CinemachineVirtualCamera currentVirtualCamera = _currentVirtualCamera;
        while (timer < duration)
        {
            timer += Time.deltaTime;
            // 限制进度不超过1，避免因浮点误差导致过度
            float progress = Mathf.Min(timer / duration, 1f);
            // 修复2：使用SmoothStep增强过渡手感（可选）
            float smoothProgress = 1 - Mathf.Pow(1 - progress, 3); // 3次幂曲线，可调整幂次控制加速程度

            // 插值正交大小
            currentVirtualCamera.m_Lens.OrthographicSize = Mathf.Lerp(currentCameraOrthographicSize, originalOrthographicSize, smoothProgress);

            yield return null;
        }
        _cameraRecoveryFocusCoroutine = null;
    }
}
